
'use strict'

/***
 * @(1)类型声明
 * **/
//1
function add(type: string){  //默认类型参数
    console.log(type);
}

// add(12);
add('12')

//2
function demo(type: string): void { //函数没有返回值
    console.log(type);
    // return  type;
}

demo('1')

//3
let a: any = '1'
let b = 1 // === let b: number = 1;
// b = '12' 报错
let c // === let c: any;
c = '1'
c = 12



/***
 * @(2)联合类型声明
 * **/
let d: string | number = '1';
d = 2;

function demo1(val: string | number): any{
    // 必须返回值 值得类型任意
    //参数不确定时 参数只能调用两种类型共有的方法
    //return  val.length //所以报错
    return val.toString();
}


/***
 * @(3)对象类型-接口
 * **/
interface Person {
    name: string;
    age: number;
}

let tom: Person = {
    name: 'Tom',
    age: 25,
    // class:""  //只能是两种属性 并且属性值类型确定  有且只有
};

//可选属性
interface Person1 {
    name: string;
    age: number;
    class?: string; // 可选属性 有或没有 有必须为string
}
let tom1: Person1 = {
    name: 'Tom',
    age: 25,
};

//任意属性
interface Person3 {
    name: string;
    age?: number;
    [propName: string]: any; //上面age的可选属性为 number 是 任意属性any的子集 所以不报错
}

let tom3: Person3 = {
    name: 'Tom',
    gender: 'male'
};

interface Person4 {
    name: string;
    // age?: number;
    // [propName: string]: string; //上面age的可选属性为 number 不是 任意属性any的子集 所以报错
}

interface Person5 {
    name: string;
    age?: number;
    [propName: string]: string | number; //用于定义不确定属性，不确定属性值类型
}

//只读属性
interface Person6 {
    readonly id: number; //只读属性
    name: string;
    age?: number;
    [propName: string]: any;
}
let tom6: Person6 = {
    id: 89757,
    name: 'Tom',
    gender: 'male'
};
// tom.id = 9527; //报错


/***
 * @(4)数组的类型
 * **/
//简单表示法
let fibonacci: number[] = [1, 1, 2, 3, 5];
// let fibonacci2: number[] = [1, '1', 2, 3, 5]; //报错 定义一个已number为值得数组 不能有其他类型的值

//数组泛型  待扩展。。。。。。。。。。。。。。。
let fibonacci2: Array<number> = [1, 1, 2, 3, 5];

//接口表示  不常用 主要用于内数组
interface NumberArray {
    [index: number]: number;
}
let fibonacci3: NumberArray = [1, 1, 2, 3, 5];
//但是常见的内数组有默认接口定义 IArguments, NodeList, HTMLCollection
//实际上 TS 内置就定义内这个接口:
interface IArguments {
    [index: number]: any;
    length: number;
    callee: Function;
}

//any 在数组中的应用
let list: any[] = ['xcatliu', 25, { website: 'http://xcatliu.com' }];




/***
 * @(4)函数的类型
 * **/
//函数声明
function add1(x: number,y: number): number{
    return  x+y;
}
//函数表达式
let add2 = function (x: number,y: number): number{
    return x+y; //可以正常编译 但是实际上add2 没有去设定他的类型
}
let add3: (x: number,y: number) => number = function (x: number,y: number): number{
    return x+y; //实际上应该这样
}

//使用接口定义函数
interface SearchFunc {
    (source: string, subString: string): boolean; // (参数) ： 返回值
}
let mySearch: SearchFunc;
mySearch = function(source: string, subString: string) {
    return source.search(subString) !== -1;
}

//可选参数
function buildName(firstName: string, lastName?: string) {
    if (lastName) {
        return firstName + ' ' + lastName;
    } else {
        return firstName;
    }
}
let tomcat = buildName('Tom', 'Cat');
let tom2 = buildName('Tom');

//可选参数后面不可再接 必需参数  但是可以接可选参数
// function buildName2(firstName?: string, lastName: string) {  //报错
//     if (lastName) {
//         return firstName + ' ' + lastName;
//     } else {
//         return firstName;
//     }
// }
function buildName2(firstName?: string, lastName?: string) {
    if (lastName) {
        return firstName + ' ' + lastName;
    } else {
        return firstName;
    }
}

//参数默认值
//参数默认值有了 那么这个参数就可以有或者没有
function buildName3(firstName: string, lastName: string = 'Cat') {
    return firstName + ' ' + lastName;
}
let tomcat3 = buildName('Tom', 'Cat');
let tom4 = buildName('Tom');
//同时他后面也可接必需参数
function buildName4(firstName: string = 'Cat', lastName: string) {
    return firstName + ' ' + lastName;
}
let tomcat4 = buildName('Tom', 'Cat');
let cat4 = buildName(undefined, 'Cat');


//剩余参数 注意： 剩余参数只能是参数的最后一个
function push(array: any[], ...items: any[]) {
    items.forEach(function(item) {
        array.push(item);
    });
}
let f = [];
push(f, 1, 2, 3);


//重载
function reverse(x: number): number;
function reverse(x: string): string;
function reverse(x: number | string): number | string | void {
    if (typeof x === 'number') {
        return Number(x.toString().split('').reverse().join(''));
    } else if (typeof x === 'string') {
        return x.split('').reverse().join('');
    }
}




/***
 * @(5)类型的断言
 * **/
